/*
 * =====================================================================================
 *
 *       Filename:  echo_udp_svr.cpp
 *
 *    Description:  udp的echo svr
 *
 *        Version:  1.0
 *        Created:  2008年09月03日 16时33分29秒
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  ZhixiongHong (hzx), fishwarter@gmail.com
 *        Company:  Unioncast
 *
 * =====================================================================================
 */

#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

#define MAX_LINE 	1024

void dg_cli(FILE* fp, int sockfd, sockaddr* pserver, int len);

int main(int argc, char** argv)
{
	if( argc != 3)
	{
		cout << "useage: " << argv[0] << " host  port " << endl;
		return -1;
	}
	
	unsigned short port = atoi(argv[2]);
	
	struct sockaddr_in	serverAddr;
	
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if( sockfd < 0 )
	{
		cout << "can't create socket " << endl;
		return -1;
	}
	
	bzero(&serverAddr, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(port);
	inet_pton(AF_INET, argv[1], &serverAddr.sin_addr);
			
	dg_cli(stdin, sockfd, (sockaddr* )&serverAddr, sizeof(serverAddr));
	return 0;
}


void dg_cli(FILE* fp, int sockfd, sockaddr* pserver, int len)
{
	int 		n;
	char 		sendline[MAX_LINE], recvline[MAX_LINE+1];
	struct 		sockaddr_in reply_addr;
	socklen_t	reply_len;

	while(fgets(sendline, MAX_LINE, fp) != NULL)
	{
		sendto(sockfd, sendline, strlen(sendline), 0, pserver, len);
		/*
		 * n = recvfrom(sockfd, recvline, MAX_LINE, 0, NULL, NULL);
		 * 将后面的参数指定为NULL，表示不关心应答数据从何而来，但这样可能存在风险，
		 * 因为任何进程都可以往客户端绑定的端口(客户端一般是系统分配的)发送数据。这些
		 * 的话就不能区分数据是由谁获取到的,这样就可以做如下的修改	
			
		 * 经试验果然如此	
 		*/
		n = recvfrom(sockfd, recvline, MAX_LINE, 0, (sockaddr *)&reply_addr, &reply_len);
		if( len != (int)reply_len || memcmp(pserver, &reply_addr, len) != 0 )
		{
			cout << "reply from %s ignored"  << inet_ntoa(reply_addr.sin_addr)  << ": " 
				<< ntohs(reply_addr.sin_port)<< endl; 
			continue;
		}
		recvline[n] = 0;
		cout << recvline << endl;
	}
	
}

